package edu.ncsu.csc.ip.routing.dv;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Class <code>Node</code>
 * 
 *  Graph Node contains neighbor map and distance vector 
 * 
 * @author Moin Ayazifar <mayazif@ncsu.edu>
 * @author Steven Elliott <sdelliot@ncsu.edu>
 * 
 */

public final class Node implements Cloneable {

	private final String name;
	//Map<NeighborNode, RE<NeighborNode, Weight>>
	public final Map<Node, RouteEntity> neighborsMap = new ConcurrentHashMap<Node, RouteEntity>();

	public RouterLocal router;

	//FromNode : Map<ToNode, RE<ThruNode, Weight>> 
	public Map<Node, RouteEntity> distanceVector = new ConcurrentHashMap<Node, RouteEntity>();

	public Node(String name) {
		this.name = name;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	@Override
	public String toString() {
		return getName();
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object node) {
		if (this == node)
			return true;
		if (node == null)
			return false;
		if (getClass() != node.getClass())
			return false;
		Node otherNode = (Node) node;
		if (name == null) {
			if (otherNode.name != null)
				return false;
		} else if (!name.equals(otherNode.name))
			return false;
		return true;
	}

	public synchronized void printDv() {
		for (Node destNode : distanceVector.keySet()) {
			System.out.println(name + " To: " + destNode + " weight: "
					+ distanceVector.get(destNode).weight + " through: "
					+ distanceVector.get(destNode).nextNode);
		}

	}
	
	public  synchronized void printRoutingTable() {

		System.out.println("---------Routing Table of Node " + name
				+ "-------------");
		System.out.println("DestNode		ThruNode		Cost");

		Node[] nodes = distanceVector.keySet().toArray(
				new Node[distanceVector.size()]);
        // Sort is not needed
		//Arrays.sort(nodes, distance_vector.NodeComparator);

		for (Node v : nodes) {
			if (!v.equals(this))
				System.out.println(v + "		"
						+ this.distanceVector.get(v).nextNode + "		"
						+ this.distanceVector.get(v).weight );
		}
		System.out.println("--------------------------------------------------------\n\n");
	}

	// Router is not cloned
	public Node clone() {
		Node cloned = new Node(this.name);
		for (Node destNode : this.distanceVector.keySet()) {
			cloned.distanceVector.put(destNode,
					this.distanceVector.get(destNode));
		}
		return cloned;
	}

	
}
